public class Gene extends RectObject
{
  int colorForKnownGene;
  int colorForUnknownGene;
  int fillColor;
  int highlightColor;
  
  int start;
  int stop; 
  int length;
  boolean pointsRight;
  String known; 
  String toxinName;
  
  //float x1, x2, y1, y2;//static position/former position
  //Integrator dynX1, dynX2, dynY1, dynY2;//current position
  
  Contig parentContig;
  
  Gene( Contig parentContig, float x1, float y1, float x2, float y2, int start, int stop, String known, String toxinName )
  {
    super( x1, y1, x2, y2 );
    
    this.start = start;
    this.stop = stop;
    this.length = abs(stop-start);
    this.known = known;
    this.toxinName = toxinName.trim();
    
    this.parentContig = parentContig;
    
    pointsRight = true;
    if( start > stop )
      pointsRight = false; 
    
    colorForKnownGene = 0xFF5386D4;
    colorForUnknownGene = 0xFFAEAEAD;//0xFFABAD9D;//0x7D646464;
    if( known.equalsIgnoreCase( "known" ) || known.equalsIgnoreCase( "other" ) || known.equalsIgnoreCase( "putative" ))
    {
      fillColor = colorForKnownGene;
    }
    else
      fillColor = colorForUnknownGene;
    
     highlightColor = 0x7B636363;//0x4B636363;//0x33FFF55B;
  }
   //---------------------------------------------DRAW METHODS---------------------------------------------------
  void draw()
  {
    super.draw();
    
    rectMode( CORNERS );
    fill( fillColor );
    stroke( fillColor );
    //roundRect( getX1(), getY1(), getX2(), getY2() );
    
    if( pointsRight )
    {
      drawArrowHeadRight();// getX2(), getY2(), getX1(), getY1());
    }
    else
    {
      drawArrowHeadLeft();// getX1(), getY1(), getX2(), getY2());
    }
    
    if( mouseIsOver() )
    {
      //println( "in gene for loop, noting mouseIsOver " );
      drawHover();
    }
  }
  
  
  void drawArrowHeadRight()
  {
    if( abs( parentContig.getY1() - parentContig.getY2() ) < 10 )
    {
      strokeWeight( .5 );
      float ymid = (getY2()+getY1())/2;
      line( getX1(), ymid, getX2()-1, ymid );
      return;
    }
    
    strokeWeight( 1 );
    float percOfGeneHeight = 1.0;
    float h = abs(getY2() - getY1() ) * percOfGeneHeight;
    float ymid = (getY2()+getY1())/2;
    line( getX1(), ymid, getX2()-1, ymid );
    triangle( getX2(), ymid , getX2()-h, ymid-h, getX2()-h, ymid+h);
  }
 
  void drawArrowHeadLeft()
  {
    if( abs( parentContig.getY1() - parentContig.getY2() ) < 10 )
    {
      strokeWeight( .5 );
      float ymid = (getY2()+getY1())/2;
      line( getX1(), ymid, getX2()-1, ymid );
      return;
    }
    
    strokeWeight( 1 );//(int) abs( getY1() - getY2() ));
    
    float percOfGeneHeight = 1.0;
    float h = abs(getY2() - getY1() ) * percOfGeneHeight;
    float ymid = (getY2()+getY1())/2;
    line( getX1(), ymid, getX2()-1, ymid );
    triangle( getX1(), ymid , getX1()+h, ymid-h, getX1()+h, ymid+h);
  }
  //------------------------------------------END DRAW METHODS--------------------------------------------------
  
  //------------------------------------------INTERACTIVITY METHODS-----------------------------------------------------
  boolean mouseIsOver()
  {
    float parentHalfHeight = (parentContig.getY2()-parentContig.getY1())/2;
    return ( mouseX >= (getX1()-1 ) && mouseX <= (getX2()+1 ) && mouseY >= (getY1() - parentHalfHeight) && mouseY <= (getY2() + parentHalfHeight) && parentContig.mouseIsOverPrecise() );
  }
  
  boolean isOver( float x, float y )
  {
    float parentHalfHeight = (parentContig.getY2()-parentContig.getY1())/2;
    return ( x >= (getX1()-1) && x <= (getX2()+1)  && y >= (getY1() - parentHalfHeight) && y <= (getY2() + parentHalfHeight) );
  }
  
  void drawHover()
  {
      drawBackgroundHighlight();
      drawInfoBox(); 
      fill( fillColor );
      drawGeneEnlarged();
  }
  
  void drawHighlightOnly()
  {
    drawBackgroundHighlight();
    drawGeneEnlarged();
  }
  
  void drawInfoBox()
  {
    int theTextSize = 15;
    textSize( theTextSize );
    String displayText1 = toxinName;
    String displayText2 = start + "-" + stop + " length = " + length + ", " + known;
    
    //draw hover box
    float hoverBoxWidth = textWidth( displayText2 );
    //fill( 100, 100, 100, 75 );
    fill( 10, 10, 10 );//, 0, 0, 200 );
    //fill( highlightColor );
    stroke( highlightColor );
    strokeWeight(2 );
    rectMode( CORNERS );
    //rect( (getX1()+getX2())/2 - hoverBoxWidth/2 , getY1()-3*theTextSize-theTextSize/3, (getX1()+getX2())/2 + hoverBoxWidth/2, getY1()-theTextSize/3 ) ;
    rect( (getX1()+getX2())/2 - hoverBoxWidth/2 , parentContig.getY1()-3*theTextSize-theTextSize/3, (getX1()+getX2())/2 + hoverBoxWidth/2, parentContig.getY1()-theTextSize/3 ) ;

    //draw informational text
    textAlign( CENTER, CENTER );
    fill( 255, 255, 255);
    float x = (getX1()+getX2())/2;
    float y = parentContig.getY1()-2*theTextSize-theTextSize/2;
    if( toxinName.length() > 0 )
      text( displayText1, x, y );
    else
      text( "unknown name", x, y );  
    text( displayText2, x, y + theTextSize + theTextSize/2 );
  }
  
  void drawBackgroundHighlight()
  {
    fill( highlightColor );//100, 100, 100, 75 );//highlightColor );
    stroke( highlightColor );//100, 100, 100, 75 ); //highlightColor );
    //float percOfGeneHeight = 2.0;
   // float h = abs(getY2() - getY1() ) * percOfGeneHeight;
    rect( getX1()-3, parentContig.getY1(), getX2()+3, parentContig.getY2() );
  }
  
  void drawGeneEnlarged()
  {
    if( pointsRight )
    {
      drawEnlargedArrowHeadRight();// getX2(), getY2(), getX1(), getY1());
    }
    else
    {
      drawEnlargedArrowHeadLeft();// getX1(), getY1(), getX2(), getY2());
    } 
  }
  
  void drawEnlargedArrowHeadRight()
  {
    if( abs( getY1() - getY2() ) < 1 )
    {
      //draw back highlight
      //stroke( highlightColor );
      //strokeWeight( 4.0 );
      float ymid = (getY2()+getY1())/2;
      //line( getX1(), ymid, getX2()-tx(1), ymid );
      
      //draw front line
      stroke( fillColor );
      strokeWeight( 4.0 );
      line( getX1(), ymid, getX2()-1, ymid );
      return;
    }
    stroke(fillColor);
    fill( fillColor);
    strokeWeight( 2 );//abs( getY1() - getY2() ) );
    float percOfGeneHeight = 2.0;
    float h = abs(getY2() - getY1() ) * percOfGeneHeight;
    float ymid = (getY2()+getY1())/2;
    line( getX1(), ymid, getX2()-1, ymid );
    triangle( getX2(), ymid , getX2()-h, ymid-h, getX2()-h, ymid+h);
  }
 
  void drawEnlargedArrowHeadLeft()
  {
    if( abs( getY1() - getY2() ) < 1 )
    {
      //stroke( highlightColor );
      //strokeWeight( 4.0 );
      float ymid = (getY2()+getY1())/2;
      //line( getX1(), ymid, getX2()-tx(1), ymid );
      
      stroke( fillColor );
      strokeWeight( 4.0 );
      line( getX1(), ymid, getX2()-1, ymid );
      return;
    }
    stroke(fillColor);
    fill( fillColor);
    strokeWeight( 2);//(int) abs( getY1() - getY2() ));
    float percOfGeneHeight = 2.0;
    float h = abs(getY2() - getY1() ) * percOfGeneHeight;
    float ymid = (getY2()+getY1())/2;
    line( getX1(), ymid, getX2()-1, ymid );
    triangle( getX1(), ymid , getX1()+h, ymid-h, getX1()+h, ymid+h);
  }
  //------------------------------------------END INTERACTIVITY METHODS-------------------------------------------------
  
  //------------------------------------------ANIMATION METHODS--------------------------------------------------

  //---------------------------------------END ANIMATION METHODS-------------------------------------------------
  
  //----------------------------------------------SETTERS-------------------------------------------------------------
  
  void setColors( int fc, int hc )
  {
    fillColor = fc;
    highlightColor = hc;
  }
  
  void setColor( int fc )
  {
    println( "set color ");
    fillColor = fc;
  }
  
  void flip()
  {
    println( "gene flipping" );
    int temp = start;
    start = stop;
    stop = temp;
    pointsRight = !pointsRight;
  }
  
  //---------------------------------------------END SETTERS----------------------------------------------------------
  
  //---------------------------------------------GETTERS---------------------------------------------------------
  int getStart()
  {
    return start;
  }
  
  int getStop()
  {
    return stop;
  }
  
  int getGreatestNT()
  {
    if( stop > start )
      return stop;
    return start;
  }
  
  String getToxinName()
  {
    return toxinName;
  }
  
  int getLength()
  {
    return length;
  }
  //--------------------------------------------END GETTERS------------------------------------------------------
  
  //-----------------------------------------------UTILITY METHODS-----------------------------------------------
  String toString()
  {
    return start + " " + stop + " " + known + " " + toxinName;
  }
  
  boolean equals(Gene other)
  {
    if( toxinName.equalsIgnoreCase("na") )
     return length == other.getLength();
    return toxinName.equalsIgnoreCase( other.getToxinName() );
  }
}
